﻿#include <napi.h>
#include <Magick++.h>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;
using namespace Magick;


Napi::Value FlipHorizontal(const Napi::CallbackInfo &info) {
    Napi::Env env = info.Env();

    // 参数校验（保持不变）
    if (info.Length() < 2) {
        Napi::TypeError::New(env, "需要至少两个参数：输入路径和输出路径").ThrowAsJavaScriptException();
        return env.Null();
    }

    string inputPath = info[0].As<Napi::String>();
    string outputPath = info[1].As<Napi::String>();
    float x = 0.5f;
    if (info.Length() >= 3 && !info[2].IsUndefined()) {
        x = info[2].As<Napi::Number>().FloatValue();
    }

    if (fabs(x) > 1.0f) {
        Napi::Error::New(env, "参数x必须在[-1, 1]范围内").ThrowAsJavaScriptException();
        return env.Null();
    }
    bool isNegative = x < 0;
    x = fabs(x);

    try {
        InitializeMagick(nullptr);
        vector<Image> frames;
        readImages(&frames, inputPath);
        

        // 保存原始属性（保持不变）
        int iterations = frames.empty() ? 0 : frames.front().attribute("loop").empty() ? 0 : stoi(frames.front().attribute("loop"));
        vector<unsigned int> delays;
        vector<int> disposes;
        for (const auto &frame : frames) {
            delays.push_back(frame.animationDelay());
            disposes.push_back(frame.attribute("dispose").empty() ? 0 : stoi(frame.attribute("dispose")));
        }

        if (frames.size() > 1) {
            coalesceImages(&frames, frames.begin(), frames.end());
        }

        for (auto &frame : frames) {
            if (isNegative) {
                frame.flop();
            }

            size_t width = frame.columns();
            size_t height = frame.rows();
            size_t flipWidth = static_cast<size_t>(x * width);
            
            // 计算需要扩展的画布宽度（当x>0.5时）
            size_t newWidth = width;
            if (x > 0.5f) {
                newWidth = width + (flipWidth - (width - flipWidth));
            }

            // 创建新画布
            Image newFrame(Geometry(newWidth, height), Color("transparent"));
            newFrame.composite(frame, 0, 0, OverCompositeOp);

            // 裁剪并翻转左侧部分
            Image flipped = newFrame;
            flipped.crop(Geometry(flipWidth, height, 0, 0));
            flipped.flop();

            // 清除目标区域（关键修改）
            newFrame.fillColor(Color("transparent"));
            newFrame.draw(DrawableRectangle(flipWidth, 0, newWidth, height));

            // 覆盖翻转后的图像
            newFrame.composite(flipped, flipWidth, 0, OverCompositeOp);

            frame = newFrame;

            if (isNegative) {
                frame.flop();
            }
        }

        // 恢复动画属性（保持不变）
        for (size_t i = 0; i < frames.size(); ++i) {
            frames[i].animationDelay(delays[i]);
            frames[i].attribute("dispose", to_string(disposes[i]));
        }
        if (!frames.empty()) {
            frames.front().attribute("loop", to_string(iterations));
        }

        // 输出（保持不变）
        if (frames.size() > 1) {
            optimizeImageLayers(&frames, frames.begin(), frames.end());
            writeImages(frames.begin(), frames.end(), outputPath);
        } else {
            frames[0].write(outputPath);
        }
    } catch (exception &err) {
        Napi::Error::New(env, "最外层未知错误").ThrowAsJavaScriptException();
        Napi::Error::New(env, err.what()).ThrowAsJavaScriptException();
    }
    return env.Null();
}

Napi::Value FlipVertical(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    // 参数校验
    if (info.Length() < 2) {
        Napi::TypeError::New(env, "需要至少两个参数：输入路径和输出路径").ThrowAsJavaScriptException();
        return env.Null();
    }

    string inputPath = info[0].As<Napi::String>();
    string outputPath = info[1].As<Napi::String>();
    float y = 0.5f;
    if (info.Length() >= 3 && !info[2].IsUndefined()) {
        y = info[2].As<Napi::Number>().FloatValue();
    }

    bool isNegative = y < 0;
    y = fabs(y);
    if (y > 1.0f) {
        Napi::Error::New(env, "参数y必须在[-1, 1]范围内").ThrowAsJavaScriptException();
        return env.Null();
    }

    try {
        InitializeMagick(nullptr);
        vector<Image> frames;
        readImages(&frames, inputPath);

        // 保存原始属性
        int iterations = frames.empty() ? 0 : frames.front().attribute("loop").empty() ? 0 : stoi(frames.front().attribute("loop"));
        vector<unsigned int> delays;
        vector<int> disposes;
        for (const auto &frame : frames) {
            delays.push_back(frame.animationDelay());
            disposes.push_back(frame.attribute("dispose").empty() ? 0 : stoi(frame.attribute("dispose")));
        }

        if (frames.size() > 1) {
            coalesceImages(&frames, frames.begin(), frames.end());
        }

        for (auto &frame : frames) {
            if (isNegative) {
                frame.flip();
            }

            size_t width = frame.columns();
            size_t height = frame.rows();
            size_t flipHeight = static_cast<size_t>(y * height);
            
            // 计算需要扩展的画布高度
            size_t newHeight = height;
            if (y > 0.5f) {
                newHeight = height + (flipHeight - (height - flipHeight));
            }

            // 创建新画布
            Image newFrame(Geometry(width, newHeight), Color("transparent"));
            newFrame.composite(frame, 0, 0, OverCompositeOp);

            // 裁剪并翻转顶部部分
            Image flipped = newFrame;
            flipped.crop(Geometry(width, flipHeight, 0, 0));
            flipped.flip();

            // 清除目标区域
            newFrame.fillColor(Color("transparent"));
            newFrame.draw(DrawableRectangle(0, flipHeight, width, newHeight));

            // 覆盖翻转后的图像
            newFrame.composite(flipped, 0, flipHeight, OverCompositeOp);

            frame = newFrame;

            if (isNegative) {
                frame.flip();
            }
        }

        // 恢复动画属性
        for (size_t i = 0; i < frames.size(); ++i) {
            frames[i].animationDelay(delays[i]);
            frames[i].attribute("dispose", to_string(disposes[i]));
        }
        if (!frames.empty()) {
            frames.front().attribute("loop", to_string(iterations));
        }

        // 输出
        if (frames.size() > 1) {
            optimizeImageLayers(&frames, frames.begin(), frames.end());
            writeImages(frames.begin(), frames.end(), outputPath);
        } else {
            frames[0].write(outputPath);
        }
    } catch (exception &err) {
        Napi::Error::New(env, err.what()).ThrowAsJavaScriptException();
    }
    return env.Null();
}

Napi::Value Create3DRotationGIF(const Napi::CallbackInfo &info) {
    Napi::Env env = info.Env();

    // 参数校验
    if (info.Length() < 2) {
        Napi::TypeError::New(env, "需要至少两个参数：输入路径和输出路径").ThrowAsJavaScriptException();
        return env.Null();
    }

    string inputPath = info[0].As<Napi::String>();
    string outputPath = info[1].As<Napi::String>();

    try {
        InitializeMagick(nullptr);
        
        // ========== 内部参数配置 ==========
        const int frameCount = 36;          // 动画总帧数
        const int cubeSize = 300;           // 立方体边长(像素)
        const int duration = 50;            // 每帧持续时间(毫秒)
        const double perspective = 800.0;   // 透视强度(值越小透视效果越强)
        const double rotationSpeed = 2.0;   // 旋转速度系数
        const double ambientLight = 0.3;    // 环境光强度(0-1)
        const double diffuseLight = 0.7;    // 漫反射强度(0-1)
        const int outputSize = 500;        // 输出画布大小
        
        // ========== 3D变换相关函数 ==========
        auto project3D = [perspective](double x, double y, double z) {
            double factor = perspective / (perspective + z);
            return std::make_pair(x * factor, y * factor);
        };

        // ========== 加载源图像 ==========
        vector<Image> frames;
        readImages(&frames, inputPath);
        Image sourceImage = frames.empty() ? Image(Geometry(cubeSize, cubeSize), Color("white")) : frames[0];
        sourceImage.resize(Geometry(cubeSize, cubeSize));
        
        // 创建6个面的图像(带简单光照效果)
        auto createFace = [&](double lightFactor) {
            Image face = sourceImage;
            // 应用光照效果
            face.modulate(100, 100, 100 + lightFactor * 30);
            return face;
        };

        // 立方体6个面(前,后,左,右,上,下)
        vector<Image> cubeFaces = {
            createFace(diffuseLight),   // 前(正光)
            createFace(ambientLight),   // 后(背光)
            createFace(diffuseLight*0.7), // 左(侧光)
            createFace(diffuseLight*0.7), // 右(侧光)
            createFace(diffuseLight*0.5), // 上(弱光)
            createFace(diffuseLight*0.5)  // 下(弱光)
        };

        // 立方体顶点(3D坐标)
        vector<vector<double>> cubeVertices = {
            {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, // 前
            {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1}       // 后
        };

        // 立方体面(顶点索引)
        vector<vector<int>> cubeFacesIndices = {
            {0, 1, 2, 3}, // 前
            {4, 5, 6, 7}, // 后
            {0, 3, 7, 4}, // 左
            {1, 2, 6, 5}, // 右
            {3, 2, 6, 7}, // 上
            {0, 1, 5, 4}  // 下
        };

        // 清空frames，准备创建动画帧
        frames.clear();

        // ========== 创建动画帧 ==========
        for (int i = 0; i < frameCount; ++i) {
            double angle = (360.0 * i) / frameCount * (M_PI / 180.0) * rotationSpeed;
            
            // 创建透明背景的画布
            Image frame(Geometry(outputSize, outputSize), Color("transparent"));
            frame.backgroundColor(Color("transparent"));
            
            // 旋转矩阵
            double cosA = cos(angle);
            double sinA = sin(angle);
            
            // 旋转立方体顶点
            vector<vector<double>> rotatedVertices;
            for (const auto& v : cubeVertices) {
                // 绕Y轴旋转
                double x = v[0] * cosA - v[2] * sinA;
                double z = v[0] * sinA + v[2] * cosA;
                rotatedVertices.push_back({x, v[1], z});
            }
            
            // 计算每个面的中心深度(用于排序)
            vector<pair<double, int>> faceDepths;
            for (size_t f = 0; f < cubeFacesIndices.size(); ++f) {
                double avgZ = 0;
                for (int vi : cubeFacesIndices[f]) {
                    avgZ += rotatedVertices[vi][2];
                }
                avgZ /= cubeFacesIndices[f].size();
                faceDepths.emplace_back(avgZ, f);
            }
            
            // 按深度排序(从远到近绘制)
            sort(faceDepths.begin(), faceDepths.end(), 
                [](const pair<double, int>& a, const pair<double, int>& b) {
                    return a.first > b.first;
                });
            
            // 绘制每个面
            for (const auto& [depth, faceIdx] : faceDepths) {
                vector<pair<double, double>> facePoints;
                for (int vi : cubeFacesIndices[faceIdx]) {
                    auto [x, y] = project3D(
                        rotatedVertices[vi][0] * cubeSize/2,
                        rotatedVertices[vi][1] * cubeSize/2,
                        rotatedVertices[vi][2] * cubeSize/2
                    );
                    facePoints.emplace_back(x + outputSize/2, y + outputSize/2);
                }
                
                // 只绘制朝前的面(简单的背面剔除)
                if (depth < 0) continue;
                
                // 创建变形后的面图像
                Image face = cubeFaces[faceIdx];
                face.virtualPixelMethod(Magick::TransparentVirtualPixelMethod);
                
                // 使用正确的Affine变形参数
                std::vector<double> affineArgs = {
                    facePoints[0].first, facePoints[0].second, 0, 0,
                    facePoints[1].first, facePoints[1].second, cubeSize, 0,
                    facePoints[2].first, facePoints[2].second, cubeSize, cubeSize,
                    facePoints[3].first, facePoints[3].second, 0, cubeSize
                };
                
                // 应用透视变形
                face.distort(Magick::AffineDistortion, affineArgs.size(), affineArgs.data(), true);
                
                // 合成到帧中
                frame.composite(face, 0, 0, Magick::OverCompositeOp);
            }
            
            // 设置动画属性
            frame.animationDelay(duration / 10); // 转换为1/100秒单位
            frame.attribute("dispose", "1");     // 背景处理方式
            
            frames.push_back(frame);
        }
        
        // 设置循环属性
        if (!frames.empty()) {
            frames.front().attribute("loop", "0"); // 无限循环
        }
        
        // 输出GIF
        if (frames.size() > 1) {
            optimizeImageLayers(&frames, frames.begin(), frames.end());
            writeImages(frames.begin(), frames.end(), outputPath);
        } else {
            frames[0].write(outputPath);
        }
    } catch (exception &err) {
        Napi::Error::New(env, "创建3D旋转GIF时出错").ThrowAsJavaScriptException();
        Napi::Error::New(env, err.what()).ThrowAsJavaScriptException();
    }
    return env.Null();
}

Napi::Object Init(Napi::Env env, Napi::Object exports)
{
    exports.Set(Napi::String::New(env, "flipHorizontal"),
                Napi::Function::New(env, FlipHorizontal));
    exports.Set(Napi::String::New(env, "flipVertical"),
                Napi::Function::New(env, FlipVertical));
    exports.Set(Napi::String::New(env, "create3DRotationGIF"),
                Napi::Function::New(env, Create3DRotationGIF));
    return exports;
}

NODE_API_MODULE(imageflip, Init)